package com.common.utils;

import cn.hutool.core.date.DateUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTPayload;
import cn.hutool.jwt.JWTUtil;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.common.apiresult.ResultCode;
import com.common.constant.AuthConstant;
import com.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author liuxuhuang
 * @date 2023年04月02日 8:35
 */
@Component
@Slf4j
public class JwtTokenUtil implements Serializable {

    /**
     * jwt签名密钥
     */
    private final JWTSigner jwtSigner = JWTSignerUtil.hs384(AuthConstant.JWT_TOKEN_SECRET.getBytes(StandardCharsets.UTF_8));

    /**
     * 生成jwtToken
     *
     * @param userId
     * @param userName
     * @return
     */
    public String createToken(long userId, String userName) {
        Map<String, Object> paylod = new HashMap<>();
        LocalDateTime signTime = LocalDateTime.now();
        paylod.put(JWTPayload.ISSUED_AT, signTime);
        paylod.put(JWTPayload.NOT_BEFORE, signTime);
        paylod.put(JWTPayload.EXPIRES_AT, DateUtil.offsetSecond(Date.from(signTime.atZone(ZoneId.systemDefault()).toInstant()), AuthConstant.JWT_TOKEN_EXPIRETIME));
        paylod.put("userId", userId);
        paylod.put("userName", userName);
        String token = JWTUtil.createToken(paylod, jwtSigner);
        return AuthConstant.JWT_TOKEN_PREFIX.concat(token);
    }

    /**
     * 验证token是否合法
     *
     * @param token
     * @return
     */
    public boolean vertiyToken(String token) {
        boolean verify = false;
        try {
            token = token.replaceAll(AuthConstant.JWT_TOKEN_PREFIX, "");
            verify = JWTUtil.verify(token, jwtSigner);
        } catch (Exception e) {
            throw new BusinessException(ResultCode.UNAUTHORIZED);
        }
        return verify;
    }

    /**
     * 获取userId
     *
     * @param token
     * @return
     */
    public long getUserId(String token) {
        token = token.replaceAll(AuthConstant.JWT_TOKEN_PREFIX, "");
        if (StringUtils.isBlank(token) && vertiyToken(token)) {
            throw new BusinessException(ResultCode.UNAUTHORIZED);
        }
        final JWT parseToken = JWTUtil.parseToken(token);
        return Long.parseLong(parseToken.getPayload("userId").toString());
    }

    /**
     * 获取userName
     *
     * @param token
     * @return
     */
    public String getUserName(String token) {
        token = token.replaceAll(AuthConstant.JWT_TOKEN_PREFIX, "");
        if (StringUtils.isBlank(token) && vertiyToken(token)) {
            throw new BusinessException(ResultCode.UNAUTHORIZED);
        }
        final JWT parseToken = JWTUtil.parseToken(token);
        return parseToken.getPayload("userName").toString();
    }

    /**
     * 从HttpServletRequest中获取token
     *
     * @param request
     * @return
     */
    public String getToken(HttpServletRequest request) {
        String token = "";
        token = request.getHeader(AuthConstant.JWT_TOKEN_HEADER);
        if (StringUtils.isBlank(token)) {
            token = (String) request.getAttribute(AuthConstant.JWT_TOKEN_HEADER);
        }
        return token;
    }
}

